<template>
  <!-- 图表容器：需设置固定宽高，确保ECharts渲染正常 -->
  <div class="chart-container" ref="chartRef"></div>
</template>

<script setup>
import { ref, onMounted, onUnmounted, watchEffect } from "vue";
import * as echarts from "echarts";

// 1. 图表容器引用（用于获取DOM元素）
const chartRef = ref(null);
// 2. ECharts实例引用（用于后续销毁和更新）
let myChart = null;

// ---------------------- 基础配置与数据 ----------------------
// X轴：周一至周五
const weekdays = ["周一", "周二", "周三", "周四", "周五"];
// 跨日时间范围
const crossDayRange = "8月10日 12:00 - 8月12日 12:00";
const crossDayTotalHours = 48; // 跨日区间总时长

// 原始停留时间数据（小时）- 若需响应式，可改为ref定义
const rawData = ref([
  [48, 10, 11, 9, 8], // 系列1
  [0, 9, 7, 10, 12], // 系列2
  [0, 12, 13, 11, 10], // 系列3
  [0, 8, 9, 10, 9], // 系列4
  [0, 9, 8, 8, 9], // 系列5
]);

// 状态数据：与rawData结构完全对应（每个数值单独指定"通行"/"不通行"）
const statusData = ref([
  ["通行", "不通行", "不通行", "通行", "通行"], // 系列1状态
  ["", "通行", "通行", "不通行", "通行"], // 系列2状态
  ["", "通行", "不通行", "通行", "不通行"], // 系列3状态
  ["", "不通行", "通行", "不通行", "通行"], // 系列4状态
  ["", "不通行", "通行", "通行", "不通行"], // 系列5状态
]);

// 状态颜色映射（统一管理颜色，便于修改）
const statusColors = {
  通行: "#4CAF50", // 绿色
  不通行: "#F44336", // 红色
};

// ---------------------- 核心方法 ----------------------
/**
 * 1. 数据校验与平衡：强制每天总和 = 48小时
 * （若rawData为ref响应式数据，修改后会触发图表更新）
 */
const balanceDailyData = () => {
  weekdays.forEach((_, dayIndex) => {
    // 计算当天所有系列的总和
    const currentSum = rawData.value.reduce(
      (sum, category) => sum + category[dayIndex],
      0
    );
    // 若总和偏差超过0.01，调整最后一个系列的数据
    if (Math.abs(currentSum - crossDayTotalHours) > 0.01) {
      rawData.value[rawData.value.length - 1][dayIndex] +=
        crossDayTotalHours - currentSum;
    }
  });
};

/**
 * 2. 构建ECharts系列配置
 * @returns {Array} 系列配置数组
 */
const buildSeries = () => {
  return rawData.value.map((data, seriesIndex) => ({
    name: `系列${seriesIndex + 1}`, // 系列内部标识（用于tooltip）
    type: "bar",
    stack: "total", // 堆叠配置：同stack值的系列会堆叠显示
    barWidth: "60%", // 柱子宽度（百分比，适配容器）
    label: {
      show: true,
      position: "inside", // 标签在柱子内部
      color: "#fff",
      fontSize: 10,
      formatter: (params) => {
        const hours = rawData.value[seriesIndex][params.dataIndex];
        const percentage = Math.round((hours / crossDayTotalHours) * 100);
        // 标签内容：状态 + 时长 + 百分比
        return `${
          statusData.value[seriesIndex][params.dataIndex]
        }\n${hours}h(${percentage}%)`;
      },
    },
    // 为每个数据点单独设置颜色（根据状态匹配）
    data: data.map((value, dataIndex) => ({
      value,
      itemStyle: {
        color: statusColors[statusData.value[seriesIndex][dataIndex]],
      },
    })),
    emphasis: {
      focus: "series", // 鼠标hover时，高亮当前系列所有数据
    },
  }));
};

/**
 * 3. 构建完整ECharts配置项
 * @returns {Object} ECharts配置对象
 */
const buildChartOption = () => {
  return {
    // 网格配置：控制图表位置，避免标签溢出
    grid: {
      left: "20%",
      right: "8%",
      top: "18%",
      bottom: "15%",
      containLabel: true, // 确保标签不会超出grid范围
    },

    // 标题配置
    title: {
      text: `时间范围：${crossDayRange}（共${crossDayTotalHours}小时）`,
      left: "center",
      top: 0,
      textStyle: {
        fontSize: 14,
        color: "#333",
        fontWeight: "normal",
      },
    },

    // 图例配置：仅显示"通行/不通行"两种状态
    legend: {
      data: [
        { name: "通行", icon: "rect", itemStyle: { color: statusColors.通行 } },
        {
          name: "不通行",
          icon: "rect",
          itemStyle: { color: statusColors.不通行 },
        },
      ],
      top: 30,
      left: "center",
      selectedMode: false, // 禁止图例选择（仅展示）
      textStyle: {
        fontSize: 12,
        color: "#666",
      },
      itemWidth: 10,
      itemHeight: 10,
    },

    // 提示框配置：鼠标hover时显示详细信息
    tooltip: {
      trigger: "axis", // 按轴触发（整列数据）
      axisPointer: { type: "shadow" }, // 阴影指示器
      backgroundColor: "rgba(255,255,255,0.95)",
      borderColor: "#eee",
      borderWidth: 1,
      padding: 12,
      textStyle: { color: "#333", fontSize: 12 },
      formatter: (params) => {
        const day = weekdays[params[0].dataIndex];
        let content = `
          <div style="font-weight:600;margin-bottom:6px;">${day}</div>
          <div style="margin-bottom:4px;color:#666;">时间范围：${crossDayRange}</div>
          <div style="margin-bottom:4px;color:#666;">当日总时长：${crossDayTotalHours}小时</div>
        `;
        // 按数值大小排序，便于查看
        const sortedParams = [...params].sort((a, b) => b.value - a.value);
        sortedParams.forEach((item) => {
          const seriesIndex = item.seriesIndex;
          const dataIndex = item.dataIndex;
          const status = statusData.value[seriesIndex][dataIndex];
          const percentage = Math.round(
            (item.value / crossDayTotalHours) * 100
          );
          content += `
            <div style="margin-bottom:2px;">
              <span style="display:inline-block;width:10px;height:10px;background:${item.color};margin-right:6px;"></span>
              ${status}（${item.seriesName}）：${item.value}小时（${percentage}%）
            </div>
          `;
        });
        return content;
      },
    },

    // X轴配置
    xAxis: {
      type: "category",
      data: weekdays,
      axisLabel: { fontSize: 14, color: "#333", interval: 0 }, // 0表示显示所有标签
      axisLine: { lineStyle: { color: "#eee" } },
      name: "星期",
      nameTextStyle: { fontSize: 13, color: "#666", padding: [10, 0, 0, 0] },
      nameLocation: "middle",
      nameGap: 30, // 名称与轴线的距离
    },

    // Y轴配置（显示时间格式）
    yAxis: {
      type: "value",
      min: 0,
      max: crossDayTotalHours,
      interval: 12, // 每12小时一个刻度
      axisLabel: {
        formatter: (value) => {
          // 计算当前刻度对应的时间（基于起始时间8月10日12:00）
          const startDate = new Date("2023-08-10T12:00:00");
          const currentDate = new Date(startDate.getTime() + value * 3600000);
          // 格式化时间为 "MM-DD HH:MM"
          const month = String(currentDate.getMonth() + 1).padStart(2, "0");
          const day = String(currentDate.getDate()).padStart(2, "0");
          const hours = String(currentDate.getHours()).padStart(2, "0");
          const minutes = String(currentDate.getMinutes()).padStart(2, "0");
          return `${month}-${day} ${hours}:${minutes}`;
        },
        fontSize: 11,
        color: "#666",
        align: "right",
        padding: [0, 10, 0, 0], // 右内边距，避免标签贴轴
      },
      axisLine: { show: false }, // 隐藏Y轴线
      splitLine: { lineStyle: { color: "#f5f5f5" } }, // 网格线样式
      name: "时间",
      nameTextStyle: { fontSize: 13, color: "#666" },
      nameLocation: "middle",
      nameGap: 110, // 名称与标签的距离
    },

    // 系列配置（调用buildSeries方法生成）
    series: buildSeries(),

    // 动画配置
    animation: true,
    animationDuration: 1000,
    animationEasing: "cubicOut", // 缓动效果
  };
};

/**
 * 4. 初始化图表
 */
const initChart = () => {
  // 确保DOM已挂载且ECharts实例未初始化
  if (!chartRef.value || myChart) return;

  // 1. 初始化ECharts实例
  myChart = echarts.init(chartRef.value);

  // 2. 平衡数据（确保每天总和为48小时）
  balanceDailyData();

  // 3. 设置配置项并渲染图表
  myChart.setOption(buildChartOption());

  // 4. 监听窗口 resize，自动适配图表大小
  window.addEventListener("resize", handleResize);
};

/**
 * 5. 销毁图表（避免内存泄漏）
 */
const destroyChart = () => {
  if (myChart) {
    // 1. 移除窗口resize监听
    window.removeEventListener("resize", handleResize);
    // 2. 销毁ECharts实例
    myChart.dispose();
    myChart = null;
  }
};

/**
 * 6. 处理窗口resize（适配图表大小）
 */
const handleResize = () => {
  myChart?.resize();
};

// ---------------------- Vue生命周期钩子 ----------------------
// 1. 挂载时初始化图表
onMounted(() => {
  initChart();
});

// 2. 卸载时销毁图表
onUnmounted(() => {
  destroyChart();
});

// 3. 监听数据变化（rawData/statusData），自动更新图表
watchEffect(() => {
  // 若图表已初始化，重新平衡数据并更新配置
  if (myChart) {
    balanceDailyData();
    myChart.setOption(buildChartOption());
  }
});
</script>

<style scoped>
/* 图表容器样式：设置固定宽高（可根据需求调整） */
.chart-container {
  width: 100%;
  height: 600px; /* 建议最小高度不低于400px，确保标签正常显示 */
  margin: 0 auto;
}
</style>
